import seltar.motion.*;

import codeanticode.glgraphics.*;

import de.fhpotsdam.unfolding.mapdisplay.*;
import de.fhpotsdam.unfolding.utils.*;
import de.fhpotsdam.unfolding.marker.*;
import de.fhpotsdam.unfolding.tiles.*;
import de.fhpotsdam.unfolding.interactions.*;
import de.fhpotsdam.unfolding.*;
import de.fhpotsdam.unfolding.core.*;
import de.fhpotsdam.unfolding.geo.*;
import de.fhpotsdam.unfolding.events.*;
import de.fhpotsdam.utils.*;
import de.fhpotsdam.unfolding.providers.*;

import processing.opengl.*;

Motion m;
int head, tail;
int arraySize = 30;
float arrx[], arry[];
String []content;
float [][]GPS;
int GPSsize;
static final float epsilon = 0.0001;
de.fhpotsdam.unfolding.Map map;
BufferedReader reader;
PVector pos[];
int heading;

float getDistance(PVector pt1, PVector pt2)
{
  float x1 = pt1.x;
  float y1 = pt1.y;
  float x2 = pt2.x;
  float y2 = pt2.y;
  return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

boolean isOnline(PVector pt, PVector startPos, PVector endPos)
{
  float dis1 = getDistance(pt, startPos);
  float dis2 = getDistance(pt, endPos);
  float disa = getDistance(startPos, endPos);
  //println("dis1 " + dis1 + " dis2 " + dis2 + " disa " + disa);
  if (abs(dis1 + dis2 - disa) < epsilon) return true;
  else return false;
}

boolean isNear()
{
  return !isOnline(new PVector(m.getX(), m.getY()), 
                   pos[heading-1], 
                   pos[heading-1]);
}

void resetMotion()
{
  m.setX(pos[0].x);
  m.setY(pos[0].y);
  head = tail = 0;
  arrx[head] = pos[0].x;
  arry[head] = pos[0].y;
  heading = 1;
}

void setup()
{
  GPSsize = 0;
//  reader = createReader("shapes.txt");
  String[] content = loadStrings("shape.txt");
  GPS = new float[content.length-1][2];
  int Size = 0;
  for (int i=1; i<content.length; ++i) {
    if (trim(content[i]).length() == 0) {
      continue; // skip empty rows
    }
    String[] pieces = split(content[i], ",");
    // copy to the table array
    GPS[Size][0] = parseFloat(pieces[1]);
    GPS[Size][1] = parseFloat(pieces[2]);
    ++Size;
  }

  head = tail = 0;
  heading = 1;
  arrx = new float[arraySize];
  arry = new float[arraySize];
  size(800, 600, GLConstants.GLGRAPHICS);
  pos = new PVector[Size];
  map = new de.fhpotsdam.unfolding.Map(this);
  //MapUtils.createDefaultEventDispatcher(this, map);
  Location loc = new Location(GPS[Size/2][0], GPS[Size/2][1]);
  map.zoomAndPanTo(loc, 12);
  loc = new Location(GPS[0][0], GPS[0][1]);
  float []xy = map.getScreenPositionFromLocation(loc);
  pos[0] = new PVector(xy[0], xy[1]);
  //println("pos[0].x: " + pos[0].x + " pos[0].y: " + pos[0].y);
  GPSsize = 1;
  for (int i=1; i<Size; ++i) {
    loc.setLat(GPS[i][0]);
    loc.setLon(GPS[i][1]);
    xy = map.getScreenPositionFromLocation(loc);
    //println("pos[i-1].x: " + pos[GPSsize-1].x + " pos[i-1].y: " + pos[GPSsize-1].y);
    if (xy[0] == pos[GPSsize-1].x && xy[1] == pos[GPSsize-1].y) continue;
    pos[GPSsize] = new PVector(xy[0], xy[1]);
    GPSsize++;
  }
  arrx[head] = pos[0].x;
  arry[head] = pos[0].y;
  m = new Motion(arrx[head], arry[head]);
}

void draw()
{
  map.draw();
  strokeWeight(5);
  fill(215, 0, 0, 80);
  for (int i=1; i<GPSsize; ++i) {
    line(pos[i-1].x, pos[i-1].y, pos[i].x, pos[i].y);
    //ellipse(pos[i].x, pos[i].y, 2, 2);
  }
  strokeWeight(2);
  fill(0, 0, 0);
  float cx = m.getX();
  float cy = m.getY();
  //println("curx: " + m.getX() + " cury: " + m.getY());
  if (isNear())
    ++heading;
  if (heading == GPSsize) {
    resetMotion();
  } else {
    m.followTo(pos[heading].x, pos[heading].y);
    m.move();
    addNewSection(cx, cy);
    drawLine();
  }
}

void drawLine()
{
  for (int i=tail; i!=head; i=(i+1) % arraySize) {
    int i1 = (i + 1) % arraySize;
    line(arrx[i], arry[i], arrx[i1], arry[i1]);
  }
}

void addNewSection(float x, float y)
{
  head = (head + 1) % arraySize;
  if (head == tail)
    tail = (tail + 1) % arraySize;
    arrx[head] = x;
    arry[head] = y;
}


